package com.xiaoyu.base;

import androidx.annotation.NonNull;

import com.tencent.bugly.crashreport.CrashReport;

import java.util.Collections;
import java.util.List;

import in.srain.cube.concurrent.AppThreads;

public class DBCall {

    public static <V> V call(Callable<V> callable) {
        try {
            return callable.call(AppDatabase.getCurrentDatabase());
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
            return null;
        }
    }

    public static <V> V callForGlobal(GlobalCallable<V> globalCallable) {
        try {
            return globalCallable.call(GlobalDatabase.getCurrentDatabase());
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
            return null;
        }
    }

    public static void run(Runnable runnable) {
        try {
            runnable.run(AppDatabase.getCurrentDatabase());
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
        }
    }

    public static void runForGlobal(GlobalRunnable globalRunnable) {
        try {
            globalRunnable.run(GlobalDatabase.getCurrentDatabase());
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
        }
    }

    @NonNull
    public static <V> List<V> listCall(Callable<List<V>> callable) {
        try {
            final List<V> list = callable.call(AppDatabase.getCurrentDatabase());
            if (list != null) {
                return list;
            }
            return Collections.emptyList();
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
            return Collections.emptyList();
        }
    }

    public static void runAsync(final Runnable runnable) {
        AppThreads.runOnDBThread(new java.lang.Runnable() {
            @Override
            public void run() {
                try {
                    runnable.run(AppDatabase.getCurrentDatabase());
                } catch (Throwable e) {
                    e.printStackTrace();
                    CrashReport.postCatchedException(e);
                }
            }
        });
    }

    public static <V> V call(String uid, Callable<V> callable) {
        try {
            return callable.call(AppDatabase.getDatabaseIfCurrentId(uid));
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
            return null;
        }
    }

    public static void run(String uid, Runnable runnable) {
        try {
            runnable.run(AppDatabase.getDatabaseIfCurrentId(uid));
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
        }
    }

    @NonNull
    public static <V> List<V> listCall(String uid, Callable<List<V>> callable) {
        try {
            final List<V> list = callable.call(AppDatabase.getDatabaseIfCurrentId(uid));
            if (list != null) {
                return list;
            }
            return Collections.emptyList();
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
            return Collections.emptyList();
        }
    }

    @NonNull
    public static <V> List<V> listCallForGlobal(GlobalCallable<List<V>> globalCallable) {
        try {
            final List<V> list = globalCallable.call(GlobalDatabase.getCurrentDatabase());
            if (list != null) {
                return list;
            }
            return Collections.emptyList();
        } catch (Throwable e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
            return Collections.emptyList();
        }
    }

    public static void runAsync(final String uid, final Runnable runnable) {
        AppThreads.runOnDBThread(() -> run(uid, runnable));
    }

    public interface Callable<V> {
        V call(AppDatabase database);
    }

    public interface GlobalCallable<V> {
        V call(GlobalDatabase globalDatabase);
    }

    public interface Runnable {
        void run(AppDatabase database);
    }

    public interface GlobalRunnable {
        void run(GlobalDatabase globalDatabase);
    }
}
